package com.foreveross.bsl.push.application.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.inject.Named;

import org.apache.commons.io.IOUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

import com.foreveross.bsl.common.utils.mapper.BeanMapper;
import com.foreveross.bsl.common.utils.web.QueryOrder;
import com.foreveross.bsl.common.utils.web.QuerySpecs;
import com.foreveross.bsl.push.application.AppChannelConfigService;
import com.foreveross.bsl.push.application.PushModuleException;
import com.foreveross.bsl.push.application.vo.AppChannelConfigVo;
import com.foreveross.bsl.push.domain.entity.channel.ApnsConfig;
import com.foreveross.bsl.push.domain.entity.channel.AppChannelConfig;
import com.foreveross.bsl.push.domain.entity.channel.InstantConfig;
import com.foreveross.bsl.push.domain.entity.channel.OpenfireConfig;
import com.foreveross.bsl.push.repository.AppChannelConfigRepository;
import com.google.common.collect.Lists;

@Named("defaultAppChannelConfigService")
public class DefaultAppChannelConfigService implements AppChannelConfigService {

    private final AppChannelConfigRepository getAppChannelConfigRepository(){
		return new AppChannelConfig().getEntityRepository(AppChannelConfigRepository.class);
	}
	
	@Override
	public boolean existsConfig(String appId) {
		return getAppChannelConfigRepository().exists(appId);
	}

	@Override
	public AppChannelConfigVo getConfig(String appId) {
		AppChannelConfig cfg=this.getAppChannelConfigRepository().findOne(appId);
		if(cfg==null){
			throw new PushModuleException("应用："+appId+"的推送配置不存在");
		}
		return BeanMapper.map(this.getAppChannelConfigRepository().findOne(appId), AppChannelConfigVo.class);
	}

	@Override
	public List<AppChannelConfigVo> getConfigs(Set<String> appIds) {
		Iterable<AppChannelConfig> cfgs = this.getAppChannelConfigRepository().findAll(appIds);
		List<AppChannelConfigVo> list = Lists.newArrayList();
		for (AppChannelConfig cfg : cfgs) {
			list.add(BeanMapper.map(cfg, AppChannelConfigVo.class));
		}
		return list;
	}

	@Override
	public Page<AppChannelConfigVo> findBy(int pageNo, int pageSize, QuerySpecs querySpecs) {
		if(querySpecs==null){
			querySpecs=new QuerySpecs();
		}
		QueryOrder qo=querySpecs.getOrder("createTime");
		if(qo==null){
			querySpecs.setOrder("createTime", QueryOrder.Direction.DESC);
		}
		Pageable pageable=PageRequestHelper.buildPageable(pageNo, pageSize);
		Page<AppChannelConfig> page = getAppChannelConfigRepository().findByQuerySpecs(querySpecs, pageable);
		Page<AppChannelConfigVo> result = new PageImpl<AppChannelConfigVo>(BeanMapper.mapList(
				page.getContent(), AppChannelConfigVo.class), pageable, page.getTotalElements());
		return result;
	}

	@Override
	public void removeConfig(String appId) {
		this.getAppChannelConfigRepository().delete(appId);
	}
	
	private AppChannelConfig createEmptyConfig(String appId){
		AppChannelConfig cfg = new AppChannelConfig();
		cfg.setAppId(appId);
		cfg.setCreateTime(new Date());
		return cfg;
	}

	@Override
	public void setApnsConfig(String appId, InputStream certInputStream, String certFilename,
			String certPassword, boolean sandbox) throws IOException {
		AppChannelConfig cfg = this.getAppChannelConfigRepository().findOne(appId);
		Date now=new Date();
		if (cfg == null) {
			cfg = createEmptyConfig(appId);
		}
		ApnsConfig apnsCfg = sandbox ? cfg.getApnsSandboxConfig() : cfg.getApnsConfig();
		if (apnsCfg == null)
			apnsCfg = new ApnsConfig();
		apnsCfg.setCertFilename(certFilename);
		apnsCfg.setCertPassword(certPassword);
		apnsCfg.setUpdateTime(now);
		apnsCfg.setCertContent(IOUtils.toByteArray(certInputStream));
		if(sandbox){
			cfg.setApnsSandboxConfig(apnsCfg);
		}
		else{
			cfg.setApnsConfig(apnsCfg);
		}
		this.getAppChannelConfigRepository().save(cfg);
	}
	
	@Override
	public void updateApnsConfig(String appId, String certPassword, boolean sandbox) {
		AppChannelConfig cfg = this.getAppChannelConfigRepository().findOne(appId);
		if (cfg == null)
			return;
		ApnsConfig apnsCfg = sandbox ? cfg.getApnsSandboxConfig() : cfg.getApnsConfig();
		if (apnsCfg == null)
			return;
		apnsCfg.setCertPassword(certPassword);
		apnsCfg.setUpdateTime(new Date());
		if(sandbox){
			cfg.setApnsSandboxConfig(apnsCfg);
		}
		else{
			cfg.setApnsConfig(apnsCfg);
		}
		this.getAppChannelConfigRepository().save(cfg);
	}

	@Override
	public void setOpenfireConfig(String appId, String username, String password) {
		AppChannelConfig cfg = this.getAppChannelConfigRepository().findOne(appId);
		if (cfg == null){
			cfg = createEmptyConfig(appId);
		}
		OpenfireConfig openfireCfg = cfg.getOpenfireConfig();
		if (openfireCfg == null)
			openfireCfg = new OpenfireConfig();
		openfireCfg.setUsername(username);
		openfireCfg.setPassword(password);
		cfg.setOpenfireConfig(openfireCfg);
		this.getAppChannelConfigRepository().save(cfg);
	}
	
	@Override
	public void setInstantConfig(String appId) {
		AppChannelConfig cfg = this.getAppChannelConfigRepository().findOne(appId);
		if (cfg == null) {
			cfg = createEmptyConfig(appId);
		}
		InstantConfig instantConfig = cfg.getInstantConfig();
		if (instantConfig == null)
			instantConfig = new InstantConfig();
		instantConfig.setChecked(true);
		cfg.setInstantConfig(instantConfig);
		this.getAppChannelConfigRepository().save(cfg);
	}
}